"""
迭代器类的定义
1.类中定义了 __iter__ 和 __next__ 两个方法
2.__iter__方法返回对象本身
3.__next__方法返回下一个元素 如果没有下一个数据则抛出 StopIteration 异常

可迭代对象
对象有 __iter__ 方法，且该方法返回一个迭代器对象(也可以返回生成器对象)
"""


# 基于可迭代对象和迭代对象实现自定义 range
class MyIteration:
    def __init__(self, n):
        print("__init__ is running")
        self.size = n
        self.num = -1

    def __iter__(self):
        print("__iter__ is running")
        return self

    def __next__(self):
        print("__next__ is running")
        if self.num >= self.size:
            raise StopIteration
        self.num += 1
        return self.num


class MyIterable:
    def __init__(self, n):
        self.n = n

    def __iter__(self):
        # return (i for i in range(self.n + 1))
        return MyIteration(self.n)  # 返回一个迭代器对象


if __name__ == "__main__":
    from collections.abc import Iterator, Iterable
    lst = [1, 2, 5]  # 列表、元组、字典都是可迭代对象
    print(dir(lst))
    print(isinstance(lst, Iterator))  # 判断对象是否是迭代器的依据是是否有 __iter__和__next__方法
    print(isinstance(lst, Iterable))  # 判断对象是否是可迭代对象的依据是是否有 __iter__方法

    it = MyIteration(5)
    # print(next(it))  # 等价于it.__next()

    print(isinstance(it, Iterator))
    print(isinstance(it, Iterable))

    # for循环 用于遍历一个可迭代器对象
    # 执行原理：先执行__iter__方法并获取返回值，然后不断的执行__next__方法将__next__的返回值传给迭代变量(有StopIteration就终止执行)
    for i in it:
        print(i)

    print("=================")
    iterable = MyIterable(5)
    print(isinstance(iterable, Iterator))
    print(isinstance(iterable, Iterable))
    for i in iterable:
        print(i)
